package com.geline.uploadfile.service;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.geline.uploadfile.enums.FileServerEnum;
import com.geline.uploadfile.pojo.UploadResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.InputStream;

/**
 * 文件上传接口定义
 * @author: mengxin
 * @date: 2022/11/11 17:41
 */
@Slf4j
public abstract class BaseUploadService {

    public abstract String getFileServerUrl();

    /**
     * 获取本地本地服务器文件根目录
     * @return
     */
    public abstract String getBucketByLocal();

    /**
     * 上传到本地服务器
     * @param tenantId
     * @param multipartFile
     * @param dirName
     * @return
     */
    public UploadResult uploadByLocal(String tenantId, MultipartFile multipartFile, String dirName){
        String originalFilename = multipartFile.getOriginalFilename();
        String fileNewName = getFileNewName(originalFilename);
        fileNewName = StrUtil.isBlank(dirName) ? fileNewName : dirName+"/"+fileNewName;

        UploadResult result = new UploadResult();
        String bucket = getBucketByLocal();
        if(!bucket.endsWith("/")){
            bucket = bucket+"/";
        }
        //文件对象：要求必须以/开关，不然会在访问url时加浏览器页面路径
        String objectName = null;
        if(StrUtil.isNotBlank(tenantId)){
            objectName = tenantId+"/"+fileNewName;
        }else {
            objectName = fileNewName;
        }
        File destFile = new File(bucket+objectName);
        try {
            FileUtil.writeFromStream(multipartFile.getInputStream(), destFile, true);
            log.info("success to upload file :　{}", destFile.getAbsoluteFile());
        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException("上传文件失败！");
        }
        result.setSysFileServer(FileServerEnum.local.name());
        result.setBucket(bucket);
        result.setObjectName(objectName);
        result.setOriginalName(originalFilename);
        result.setTenantId(tenantId);
        result.setUrl(getFileServerUrl()+objectName);
        result.setFileSize(multipartFile.getSize());
        return result;
    }

    /**
     * 上传到本地服务器
     * @param tenantId
     * @param dirName
     * @return
     */
    public UploadResult uploadByLocal(String tenantId, String originalName, InputStream inputStream, String dirName){
        String fileNewName = getFileNewName(originalName);
        fileNewName = StrUtil.isBlank(dirName) ? fileNewName : dirName+"/"+fileNewName;

        UploadResult result = new UploadResult();
        String bucket = getBucketByLocal();
        if(!bucket.endsWith("/")){
            bucket = bucket+"/";
        }
        //文件对象：要求必须以/开关，不然会在访问url时加浏览器页面路径
        String objectName = null;
        if(StrUtil.isNotBlank(tenantId)){
            objectName = tenantId+"/"+fileNewName;
        }else {
            objectName = fileNewName;
        }
        File destFile = new File(bucket+objectName);
        try {
            FileUtil.writeFromStream(inputStream, destFile, true);
            log.info("success to upload file :　{}", destFile.getAbsoluteFile());
        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException("上传文件失败！");
        }
        result.setSysFileServer(FileServerEnum.local.name());
        result.setBucket(bucket);
        result.setObjectName(objectName);
        result.setOriginalName(originalName);
        result.setTenantId(tenantId);
        result.setUrl("/"+objectName);
        result.setFileSize(destFile.length());
        return result;
    }

    /**
     * 获取本地服务器文件流
     * @param objectName
     * @return
     */
    public InputStream getFileByLocal(String bucket, String objectName){
        File file = new File(bucket+objectName);
        return FileUtil.getInputStream(file);
    }

    /**
     * 删除本地服务器文件
     * @param objectName
     * @return
     */
    public boolean deleteFileByLocal(String bucket, String objectName){
        File file = new File(bucket+objectName);
        if(FileUtil.del(file)){
            log.info("success to delete file = {} !", file.getAbsoluteFile());
        }
        return true;
    }

    /**
     * 文件重新命名
     * @param objectName
     * @return
     */
    protected String getFileNewName(String objectName) {
        int lastIndexOf = objectName.lastIndexOf(".");
        if (lastIndexOf == -1) {
            return String.format("%s_%s", StrUtil.subPre(objectName, 6), RandomUtil.randomString(5));
        } else {
            String filePrefix = objectName.substring(0, objectName.lastIndexOf("."));
            String fileSuffix = objectName.substring(objectName.lastIndexOf(".") + 1);
            return String.format("%s_%s.%s", StrUtil.subPre(filePrefix, 6), RandomUtil.randomString(5), fileSuffix);
        }
    }

    /**
     * 获取上传的根目录
     * @return
     */
    public abstract String getBucketByRemote();

    /**
     * 上传到远程服务器 (OSS, OCS, Minio)
     * @param tenantId
     * @param multipartFile
     * @param dirName
     * @return
     */
    public abstract UploadResult uploadByRemote(String tenantId, MultipartFile multipartFile, String dirName);

    public abstract UploadResult uploadByRemote(String tenantId, String originalName, InputStream inputStream, String dirName);

    /**
     * 上传到远程服务器 (OSS, OCS, Minio)使用传入的文件名
     * @param tenantId
     * @param multipartFile
     * @param dirName
     * @param fileName
     * @return
     */
    public abstract UploadResult uploadByRemote(String tenantId, MultipartFile multipartFile, String dirName, String fileName);

    /**
     * 上传到远程服务器
     * @param objectName
     * @return
     */
    public abstract InputStream getFileByRemote(String bucket, String objectName);

    /**
     * 删除远程服务器文件
     * @param objectName
     * @return
     */
    public abstract boolean deleteFileByRemote(String bucket, String objectName);
}
